package cn.ruanyun.backInterface.modules.business.staffManagement.serviceimpl;

import cn.hutool.core.util.ObjectUtil;
import cn.ruanyun.backInterface.base.RuanyunBaseEntity;
import cn.ruanyun.backInterface.common.constant.CommonConstant;
import cn.ruanyun.backInterface.common.enums.BooleanTypeEnum;
import cn.ruanyun.backInterface.common.utils.*;
import cn.ruanyun.backInterface.common.vo.Result;
import cn.ruanyun.backInterface.modules.base.pojo.User;
import cn.ruanyun.backInterface.modules.base.pojo.UserRole;
import cn.ruanyun.backInterface.modules.base.service.mybatis.IRoleService;
import cn.ruanyun.backInterface.modules.base.service.mybatis.IUserRoleService;
import cn.ruanyun.backInterface.modules.base.service.mybatis.IUserService;
import cn.ruanyun.backInterface.modules.business.order.service.IOrderService;
import cn.ruanyun.backInterface.modules.business.staffManagement.dto.StaffDto;
import cn.ruanyun.backInterface.modules.business.staffManagement.mapper.StaffManagementMapper;
import cn.ruanyun.backInterface.modules.business.staffManagement.pojo.StaffManagement;
import cn.ruanyun.backInterface.modules.business.staffManagement.service.IStaffManagementService;
import cn.ruanyun.backInterface.modules.business.staffManagement.vo.StaffListVo;
import cn.ruanyun.backInterface.modules.business.storeServicer.pojo.StoreServicer;
import cn.ruanyun.backInterface.modules.business.storeServicer.service.IStoreServicerService;
import cn.ruanyun.backInterface.modules.rongyun.Vo.RongyunLoginVo;
import cn.ruanyun.backInterface.modules.rongyun.dto.RongyunImDto;
import cn.ruanyun.backInterface.modules.rongyun.service.IRongyunService;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.springframework.web.context.request.NativeWebRequest;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;


/**
 * 员工管理接口实现
 * @author z
 */
@Slf4j
@Service
@Transactional
public class IStaffManagementServiceImpl extends ServiceImpl<StaffManagementMapper, StaffManagement> implements IStaffManagementService {


    @Autowired
    private SecurityUtil securityUtil;
    @Autowired
    private IUserService userService;
    @Autowired
    private IRoleService roleService;
    @Autowired
    private IUserRoleService userRoleService;
    @Autowired
    private IOrderService orderService;
    @Autowired
    private IRongyunService rongyunService;
    @Autowired
    private IStoreServicerService storeServicerService;


    /**
     * 添加员工
     *
     * @param staffDto 入参
     */
    @Override
    public Result<Object> addStaff(StaffDto staffDto) {


        String currentUserId = securityUtil.getCurrUser().getId();

        if (ToolUtil.isNotEmpty(staffDto.getCode())) {

           if (ToolUtil.isNotEmpty(CommonConstant.PRE_SMS.concat(staffDto.getMobile()))) {

              if (ObjectUtil.equal(staffDto.getCode(), RedisUtil.getStr(CommonConstant.PRE_SMS.concat(staffDto.getMobile())))) {

        List<User> list = userService.list(Wrappers.<User>lambdaQuery()
                .eq(User::getUsername, staffDto.getUsername())
                .or().eq(User::getMobile, staffDto.getUsername())
                .eq(User::getUsername, staffDto.getMobile())
                .or().eq(User::getMobile, staffDto.getMobile())
        );

        if (ToolUtil.isNotEmpty(list)) {

            return new ResultUtil<>().setErrorMsg(206, "已存在该用户，不可重复添加！");
        }

                    //判断是否是自己
                    User mine = userService.getById(currentUserId);
                    if (staffDto.getMobile().equals(mine.getMobile())){
                        return new ResultUtil<>().setErrorMsg(205,"不可添加自己");
                    }

                    //1.判断是否有当前手机号用户
                    return Optional.ofNullable(userService.getOne(Wrappers.<User>lambdaQuery()
                            .eq(User::getMobile, staffDto.getMobile())
                            .or().eq(User::getUsername,staffDto.getMobile())
                    ))
                            .map(user -> {

                                //2.如果有直接绑定

                                //2.1 判断是否已经绑定过
                                return  Optional.ofNullable(this.getOne(Wrappers.<StaffManagement>lambdaQuery()
                                        .eq(StaffManagement::getStaffId, user.getId())))
                                        .map(staffManagement -> new ResultUtil<>().setErrorMsg(201, "已经绑定过该员工！"))
                                        .orElseGet(() -> {

                                            //2.1 更改角色信息
                                            ThreadPoolUtil.getPool().execute(() -> {

                                                userRoleService.remove(Wrappers.<UserRole>lambdaQuery().eq(UserRole::getUserId, user.getId()));

                                                UserRole userRole = new UserRole();
                                                userRole.setUserId(user.getId()).setRoleId(roleService.getIdByRoleName(CommonConstant.STAFF))
                                                        .setCreateBy(currentUserId);
                                                userRoleService.save(userRole);

                                            });

                                            //2.2 绑定员工
                                            ThreadPoolUtil.getPool().execute(() -> {

                                                StaffManagement staffManagement = new StaffManagement();
                                                staffManagement.setStaffId(user.getId())
                                                        .setCreateBy(currentUserId);
                                                this.save(staffManagement);

                                            });
                                            return new ResultUtil<>().setSuccessMsg("绑定员工成功！");
                                        });

                            }).orElseGet(() -> {
                                //如果没有生成用户信息，绑定到一起
                                User user = new User();
                                ToolUtil.copyProperties(staffDto, user);
                                //用户密码
                                user.setPassword(new BCryptPasswordEncoder().encode("7c4a8d09ca3762af61e59520943dc26494f8941b"));
                                //获取融云token
                                rongyunService.addUser(user.getId(),"婚前婚后" + CommonUtil.getRandomNum(),CommonConstant.USER_DEFAULT_AVATAR);

                                if (userService.save(user)) {

                                    StaffManagement staffManagement = new StaffManagement();
                                    staffManagement.setStaffId(user.getId())
                                            .setCreateBy(currentUserId);
                                    this.save(staffManagement);

                                    /*//注册融云
                                    RongyunImDto rongyunImDto = new RongyunImDto();
                                    rongyunImDto.setPhone(user.getMobile())
                                            .setNickname(user.getNickName());
                                    rongyunService.registerRongyun(rongyunImDto);


                                    //更新融云token信息
                                    RongyunLoginVo rongyunLoginVo = rongyunService.loginRongyun(rongyunImDto);
                                    user.setImId(rongyunLoginVo.getId())
                                            .setImToken(rongyunLoginVo.getToken());

                                    userService.updateById(user);*/
                                }
                                //添加员工角色
                                ThreadPoolUtil.getPool().execute(() -> {

                                    UserRole userRole = new UserRole();
                                    userRole.setUserId(user.getId()).setRoleId(roleService.getIdByRoleName(CommonConstant.STAFF))
                                            .setCreateBy(currentUserId);
                                    userRoleService.save(userRole);

                                });

                                return new ResultUtil<>().setSuccessMsg("绑定员工成功！");
                            });
               }else {

                  return new ResultUtil<>().setErrorMsg(203, "验证码不一致");
               }

            }else {

                return new ResultUtil<>().setErrorMsg(204, "验证码失效");
           }

        }else {

           return new ResultUtil<>().setErrorMsg(205, "验证码为空！");
       }

    }

    /**
     * 编辑员工
     *
     * @param staffDto 入参
     */
    @Override
    public void updateStaff(StaffDto staffDto) {

       Optional.ofNullable(this.getById(staffDto.getIds())).flatMap(staffManagement ->
               Optional.ofNullable(userService.getById(staffManagement.getStaffId())))
               .ifPresent(user -> {

                   ToolUtil.copyProperties(staffDto, user);
                   userService.updateById(user);
               });
    }

    /**
     * 移除员工
     *
     * @param ids 入参
     */
    @Override
    public Result<Object> removeStaff(String ids) {

        Optional.ofNullable(ToolUtil.setListToNul(ToolUtil.splitterStr(ids)))
                .ifPresent(staffIds -> staffIds.parallelStream().forEach(staffId -> {

                    //1. 判空
                    Optional.ofNullable(this.getById(staffId)).ifPresent(staffManagement -> {

                        //1. 更改当前用户的角色信息
                        userRoleService.remove(Wrappers.<UserRole>lambdaQuery().eq(UserRole::getUserId, staffManagement.getStaffId()));

                        UserRole userRole =  new UserRole();
                        userRole.setUserId(staffManagement.getStaffId())
                                .setRoleId(roleService.getIdByRoleName(CommonConstant.DEFAULT_ROLE))
                                .setCreateBy(staffManagement.getStaffId());
                        userRoleService.save(userRole);

                        //2. 移除绑定关系

                        this.removeById(staffId);

                    });
                }));

        return new ResultUtil<>().setSuccessMsg("移除员工成功！");
    }

    /**
     * 获取员工列表
     *
     * @return StaffListVo
     */
    @Override
    public List<StaffListVo> getStaffList(StaffDto staffDto) {

        List<String> userId =  null;

        if (StringUtils.isNotBlank(staffDto.getUsername()) || StringUtils.isNotBlank(staffDto.getMobile())){

            userId = userService.list(Wrappers.<User>lambdaQuery()
                    .like(StringUtils.isNotBlank(staffDto.getUsername()),User::getUsername, staffDto.getUsername())
                    .like(StringUtils.isNotBlank(staffDto.getMobile()),User::getMobile, staffDto.getMobile())
            ).parallelStream().map(RuanyunBaseEntity::getId).collect(Collectors.toList());
        }

        return Optional.ofNullable(ToolUtil.setListToNul(this.list(Wrappers.<StaffManagement>lambdaQuery()
                .eq(StaffManagement::getCreateBy, securityUtil.getCurrUser().getId())
                .in(EmptyUtil.isNotEmpty(userId),StaffManagement::getStaffId, userId)
                .orderByDesc(StaffManagement::getCreateTime))))
        .map(staffManagements -> staffManagements.parallelStream().flatMap(staffManagement -> {

            StaffListVo staffListVo = new StaffListVo();
            Optional.ofNullable(userService.getById(staffManagement.getStaffId())).ifPresent(user ->
                    ToolUtil.copyProperties(user, staffListVo));

            staffListVo.setStaffId(staffManagement.getStaffId());

            staffListVo.setId(staffManagement.getId());

            //当前员工销售额
            staffListVo.setSaleAmount(orderService.getStaffSaleAmount(staffManagement.getStaffId()));

            //判断是是否式客服
            if (roleService.getRoleNameByUserId(staffManagement.getStaffId()).contains(CommonConstant.STORE_SERVICE)) {

                staffListVo.setIsServer(BooleanTypeEnum.YES);
            }

            return Stream.of(staffListVo);

        }).sorted(Comparator.comparing(StaffListVo::getSaleAmount)).collect(Collectors.toList()))
        .orElse(null);
    }

    @Override
    public Result<Object> setService(String id) {

        return Optional.ofNullable(this.getById(id)).map(staffManagement -> {

            //设置员工的用户id角色为客户角色
            //1.删除该员工之前的角色
            userRoleService.remove(Wrappers.<UserRole>lambdaQuery().eq(UserRole::getUserId, staffManagement.getStaffId()));


            //2.重新分配角色
            UserRole userRole = new UserRole();
            userRole.setRoleId(roleService.getIdByRoleName(CommonConstant.STORE_SERVICE))
                    .setUserId(staffManagement.getStaffId())
                    .setCreateBy(securityUtil.getCurrUser().getId());
            userRoleService.save(userRole);


            return new ResultUtil<>().setSuccessMsg("设置员工成为客户成功！");
        }).orElse(new ResultUtil<>().setErrorMsg(201, "当前记录不存在！"));
    }

    @Override
    public List<StaffManagement> getStoreServiceList(String storeId) {

        return Optional.ofNullable(ToolUtil.setListToNul(this.list(Wrappers.<StaffManagement>lambdaQuery()
        .eq(StaffManagement::getCreateBy, storeId))))
        .map(staffManagements -> staffManagements.parallelStream().filter(staffManagement ->
                roleService.getRoleNameByUserId(staffManagement.getStaffId()).contains(CommonConstant.STORE_SERVICE))
        .collect(Collectors.toList())).orElse(null);
    }

    @Override
    public String getStoreByStaffUserId(String userId) {

        return Optional.ofNullable(this.getOne(Wrappers.<StaffManagement>lambdaQuery()
        .eq(StaffManagement::getStaffId, userId)))
        .map(StaffManagement::getCreateBy)
        .orElse(null);
    }
}